home *** CD-ROM | disk | FTP | other *** search
/ MacHack 1998 / MacHack 1998.toast / Papers / C++ Exceptions / µShell / UI Classes / Windows / WindowManager.cp < prev    next >
Encoding:
Text File  |  1998-06-15  |  20.4 KB  |  822 lines  |  [TEXT/CWIE]

  1. #include "WindowManager.h"
  2. #include "Toolbox.h"
  3. #include "ToolboxEvent.h"
  4. #include "Exceptions.h"
  5. #include "EventLoop.h"
  6.  
  7. #include <LowMem.h>
  8. #include <Gestalt.h>
  9. #include <TextUtils.h>
  10.  
  11.  
  12. DefineClass2Base(WindowManager, TModule, EventFilter);
  13.  
  14.  
  15. static void            HiliteShowHideFloatingWindows(bool hiliting,bool hiding);
  16. static void            FindScreenRectWithLargestPartOfWindow(WindowRef aWindow,Rect *theBestScreenRect, GDHandle * theBestDevice);
  17. static pascal void    CalculateWindowAreaOnDevice(short depth,short deviceFlags,GDHandle targetDevice,long userData);
  18.  
  19. #pragma segment Main
  20. //--------------------------------------------------------------------------------
  21. WindowManager::WindowManager()
  22. {
  23.     fScratchRgn    = nil;
  24. }
  25.  
  26. #pragma segment AppCleanup
  27. //--------------------------------------------------------------------------------
  28. WindowManager::~WindowManager()
  29. {
  30. }
  31.  
  32. #pragma segment AppInit
  33. //--------------------------------------------------------------------------------
  34. bool WindowManager::Validate(void)
  35. {
  36.     fHasColorQuickdraw = Toolbox::HasGestalt(gestaltQuickdrawFeatures, gestaltHasColor);
  37.     fHasDisplayManager = Toolbox::HasGestalt(gestaltDisplayMgrAttr, gestaltDisplayMgrPresent);
  38.  
  39.     return true;
  40. }
  41.  
  42. #pragma segment AppInit
  43. //--------------------------------------------------------------------------------
  44. void WindowManager::Initialize(void)
  45. {
  46.     if (!fScratchRgn)
  47.     {
  48.         InitializeAfter(Toolbox::GetToolbox());
  49.  
  50.         TModule::Initialize();
  51.         EventFilter::Initialize();
  52.  
  53.         FailNIL(fScratchRgn = NewRgn());
  54.  
  55.         EventLoop::PushEventFilter(*this);
  56.     }
  57. }
  58.  
  59. //--------------------------------------------------------------------------------
  60.  
  61. void WindowManager::Finalize(void)
  62. {
  63.     TModule::Finalize();
  64.     EventFilter::Finalize();
  65. }
  66.  
  67. #pragma segment AppMain
  68. //--------------------------------------------------------------------------------
  69. bool WindowManager::Initialized(void)
  70. {
  71.     return fScratchRgn != nil;
  72. }
  73.  
  74.  
  75. #pragma segment AppInit
  76. //--------------------------------------------------------------------------------
  77. bool WindowManager::InitializeCalled(void)
  78. {
  79.     return fScratchRgn != nil;
  80. }
  81.  
  82. //--------------------------------------------------------------------------------
  83.  
  84. bool WindowManager::FilterEvent(ToolboxEvent& evt)
  85. {
  86.     EventKind    what = evt.GetEventKind();
  87.     short        part = inNoWindow;
  88.     WindowRef    wind = nil;
  89.  
  90.     switch (what)
  91.     {
  92.     case mouseDown:
  93.     case mouseUp:
  94.         part = evt.GetPartCode();
  95.         
  96.         switch (part)
  97.         {
  98.         case inDrag:
  99.             DragWindow(wind, evt.GetMousePosition());
  100.             return true;
  101.  
  102.         case inGrow:
  103.             GrowWindow(wind, evt.GetMousePosition());
  104.             return true;
  105.  
  106.         case inGoAway:
  107.             CloseWindow(wind);
  108.             return true;
  109.  
  110.         case inZoomIn:
  111.         case inZoomOut:
  112.             ZoomWindow(wind, part);
  113.             return true;
  114.         
  115.         default:
  116.             return false;
  117.         }
  118.         break;
  119.  
  120. /*    MacWindows.h
  121.  
  122.     case keyDown:
  123.     case keyUp:
  124.     case autoKey:
  125.         wind = FrontWindow(kNormalWindowLayer);
  126.         goto window_event;
  127. */
  128.  
  129.     
  130. /*
  131.     
  132.     case updateEvt:
  133.         UpdateWindow((WindowRef) msg);
  134.         break;
  135.     
  136.     case activateEvt:
  137.         if (evt.modifiers & activeFlag)
  138.         {
  139.             ActivateWindow(evt.GetWindow());
  140.         }
  141.         else
  142.         {
  143.             DeactivateWindow(evt.GetWindow());
  144.         }
  145.         break;
  146.     
  147.     case osEvt:
  148.         if (((msg & osEvtMessageMask) >> 24) == suspendResumeMessage)
  149.         {
  150.             if (msg & suspendResumeMessage)
  151.             {
  152.                 ResumeApplication();
  153.             }
  154.             else
  155.             {
  156.                 SuspendApplication();
  157.             }
  158.         }
  159.     default:
  160.         return false;
  161. */
  162.     }
  163.     
  164.     return true;
  165. }
  166.  
  167. //------------------------------------------------------------------------------
  168.  
  169. WindowRef WindowManager::NewWindow(
  170.     const Rect&            boundsRect,
  171.     ConstStr255Param    title,
  172.     bool                visible,
  173.     short                theProc,
  174.     WindowRef            behind,
  175.     bool                goAwayFlag,
  176.     long                refCon,
  177.     WindowLayer            /*layer*/)
  178. {
  179.     WindowRef win;
  180.  
  181.     if (fHasColorQuickdraw)
  182.         win = ::NewCWindow(nil,&boundsRect,title,visible,theProc,behind,goAwayFlag,refCon);
  183.     else
  184.         win = ::NewWindow(nil,&boundsRect,title,visible,theProc,behind,goAwayFlag,refCon);
  185.  
  186.     FailNIL(win);
  187.  
  188.     return win;
  189. }
  190.  
  191.  
  192. WindowRef WindowManager::GetNewWindow(
  193.     short        windowID,
  194.     WindowRef    behind,
  195.     WindowLayer    /*layer*/)
  196. {
  197.     WindowRef win;
  198.  
  199.     // get the window from the resource file
  200.     if (fHasColorQuickdraw)
  201.         win = ::GetNewCWindow(windowID, nil, behind);
  202.     else
  203.         win = ::GetNewWindow(windowID, nil, behind);
  204.  
  205.     FailNIL(win);
  206.  
  207.     return win;
  208. }
  209.  
  210.  
  211. void WindowManager::DisposeWindow(WindowRef aWindow)
  212. {
  213.     ::DisposeWindow(aWindow);
  214. }
  215.  
  216.  
  217. void WindowManager::SelectWindow(WindowRef aWindow)
  218. {
  219.     ::SelectWindow(aWindow);
  220. }
  221.  
  222. void WindowManager::UpdateWindow(WindowRef aWindow)
  223. {
  224.     ::BeginUpdate(aWindow);
  225.     DrawGrowIcon(aWindow);    
  226.     ::EndUpdate(aWindow);
  227. }
  228.  
  229. void WindowManager::ActivateWindow(WindowRef aWindow)
  230. {
  231.     ::HiliteWindow(aWindow, true);
  232. }
  233.  
  234. void WindowManager::DeactivateWindow(WindowRef aWindow)
  235. {
  236.     ::HiliteWindow(aWindow, false);
  237. }
  238.  
  239. void WindowManager::ShowWindow(WindowRef aWindow)
  240. {
  241.     ::ShowWindow(aWindow);
  242. }
  243.  
  244. void WindowManager::HideWindow(WindowRef aWindow)
  245. {
  246.     ::HideWindow(aWindow);
  247. }
  248.  
  249. void WindowManager::CloseWindow(WindowRef aWindow)
  250. {
  251.     ::CloseWindow(aWindow);
  252. }
  253.  
  254. void WindowManager::SuspendApplication()
  255. {
  256.     this->HiliteShowHideFloatingWindows(false, false);
  257. }
  258.  
  259. void WindowManager::ResumeApplication()
  260. {
  261.     this->HiliteShowHideFloatingWindows(true, true);
  262. }
  263.  
  264. void WindowManager::BeginModalDialog()
  265. {
  266.     this->HiliteShowHideFloatingWindows(false, false);
  267. }
  268.  
  269. void WindowManager::EndModalDialog()
  270. {
  271.     this->HiliteShowHideFloatingWindows(true, false);
  272. }
  273.  
  274. void WindowManager::HiliteShowHideFloatingWindows(bool active, bool /*hide*/)
  275. {
  276.     if (active)
  277.         this->ActivateWindow(FrontWindow(kNormalWindowLayer));
  278.     else
  279.         this->DeactivateWindow(FrontWindow(kNormalWindowLayer));
  280. }
  281.  
  282. WindowLayer WindowManager::GetWindowLayer(WindowRef /*aWindow*/)
  283. {
  284.     return kNormalWindowLayer;
  285. }
  286.  
  287. WindowRef WindowManager::FrontWindow(WindowLayer layer)
  288. {
  289.     switch (layer)
  290.     {
  291.     case kAnyWindowLayer:
  292.     case kNormalWindowLayer:
  293.         return ::FrontWindow();
  294.     
  295.     default:
  296.         Debugger();
  297.     }
  298.  
  299.     return nil;
  300. }
  301.  
  302. WindowRef WindowManager::BackWindow(WindowLayer layer)
  303. {
  304.     switch (layer)
  305.     {
  306.     case kAnyWindowLayer:
  307.     case kNormalWindowLayer:
  308.         {
  309.             WindowRef win;
  310.         
  311.             for (win = ::FrontWindow(); ::GetNextWindow(win); win = ::GetNextWindow(win)) {}
  312.             
  313.             return win;
  314.         }
  315.         break;
  316.         
  317.     default:
  318.         Debugger();
  319.     }
  320.  
  321.     return nil;
  322. }
  323.  
  324. //--------------------------------------------------------------------------------
  325. WindowRef WindowManager::GetNthWindow(long index, WindowLayer layer)
  326. {
  327.     WindowRef win = FrontWindow(kNormalWindowLayer);
  328.     
  329.     if (index > 0)
  330.     {
  331.         while (win != nil && --index >= 0)
  332.         {
  333.             if (index == 0)
  334.             {
  335.                 return win;
  336.             }
  337.             
  338.             win = GetNextWindow(win);
  339.         }
  340.     }
  341.     else
  342.     {
  343.         DebugStr("\pWe don't do negatives yet");
  344.     }
  345.     
  346.     
  347.     return nil;
  348. }
  349.  
  350.  
  351. //--------------------------------------------------------------------------------
  352. // find any type of window with the input name
  353. WindowRef WindowManager::GetNamedWindow(ConstStr255Param winName, WindowLayer layer)
  354. {
  355.     Str255        thisName;        
  356.  
  357.     WindowRef win = FrontWindow(kNormalWindowLayer);
  358.     
  359.     while (win != nil)
  360.     {
  361.         GetWTitle(win, thisName);
  362.         
  363.         // compare the titles
  364.         if (EqualString(winName, thisName, false, true))
  365.             return win;
  366.                 
  367.         win = GetNextWindow(win);
  368.     }
  369.  
  370.     return nil;
  371. }
  372.  
  373.  
  374. //--------------------------------------------------------------------------------
  375. /// Not done yet!!! - ONLY deals with non-floating windows
  376. long WindowManager::GetWindowIndex(WindowRef aWindow, WindowLayer layer)
  377. {    
  378.     WindowRef    win        = this->FrontWindow(kNormalWindowLayer);
  379.     long         index    = 0;
  380.     
  381.     // look for ourself among the non-floating windows
  382.     while (win != nil)
  383.     {
  384.         index++;
  385.         if (win == aWindow)
  386.             return index;
  387.  
  388.         win = ::GetNextWindow(win);
  389.     }
  390.  
  391.     return index;
  392. }
  393.  
  394.  
  395.  
  396. bool WindowManager::IsWindowVisible(WindowRef aWindow)
  397. {
  398.     return ::IsWindowVisible(aWindow);
  399. }
  400.  
  401. bool WindowManager::IsWindowHilited(WindowRef aWindow)
  402. {
  403.     return ::IsWindowHilited(aWindow);
  404. }
  405.  
  406. bool WindowManager::IsWindowModal(WindowRef aWindow)
  407. {
  408.     short    variant = ::GetWVariant(aWindow);
  409.     SInt16    kind = ::GetWindowKind(aWindow);
  410.  
  411.     return variant == kModalDialogVariantCode
  412.         || variant == kMovableModalDialogVariantCode;
  413. }
  414.  
  415. bool WindowManager::IsWindowFloating(WindowRef aWindow)
  416. {
  417.     return false;
  418. }
  419.  
  420. bool WindowManager::IsDialogWindow(WindowRef aWindow)
  421. {
  422.     return false;
  423. }
  424.  
  425. //--------------------------------------------------------------------------------
  426. bool    WindowManager::PointInStructureRgn(WindowRef aWindow, Point pt)
  427. {
  428.     GetWindowContentRgn(aWindow, fScratchRgn);
  429.     bool result = PtInRgn( pt, fScratchRgn );
  430.     return result;
  431. }
  432.  
  433. //--------------------------------------------------------------------------------
  434. bool    WindowManager::PointInContentRgn(WindowRef aWindow, Point pt)
  435. {
  436.     GetWindowContentRgn(aWindow, fScratchRgn);
  437.     bool result = PtInRgn( pt, fScratchRgn );
  438.     return result;
  439. }
  440.  
  441. //--------------------------------------------------------------------------------
  442. Rect WindowManager::GetWindowStructureBounds(WindowRef aWindow)
  443. {
  444.     GetWindowContentRgn(aWindow, fScratchRgn);
  445.     return (**fScratchRgn).rgnBBox;
  446. }
  447.  
  448. //--------------------------------------------------------------------------------
  449. Rect WindowManager::GetWindowContentBounds(WindowRef aWindow)
  450. {
  451.     GetWindowContentRgn(aWindow, fScratchRgn);
  452.     return (**fScratchRgn).rgnBBox;
  453. }
  454.  
  455. //--------------------------------------------------------------------------------
  456. void WindowManager::SetWindowBounds(WindowRef aWindow, Rect newBounds)
  457. {
  458.     ::MoveWindow( aWindow, newBounds.left, newBounds.top, false);
  459.     ::SizeWindow( aWindow, newBounds.right-newBounds.left, newBounds.bottom-newBounds.top, true );
  460. }
  461.  
  462.  
  463. //--------------------------------------------------------------------------------
  464. void WindowManager::DragWindow(WindowRef aWindow, Point startPoint)
  465. {
  466.     KeyMap        theKeyMap;
  467.     bool        commandKeyDown = false;
  468.     long        dragResult;
  469.     
  470.     if (WaitMouseUp())        //    de-bounce?
  471.     {
  472.         {
  473.             WithWindowManagerPort wmPort;
  474.  
  475.             // Set up the Window Manager port.
  476.         
  477.             SetClip(GetGrayRgn());
  478.  
  479.             // Check to see if the command key is down.
  480.         
  481.             GetKeys(theKeyMap);
  482.             commandKeyDown = ((theKeyMap[1] & 0x8000) != 0);
  483.             
  484.             if (commandKeyDown)
  485.             {
  486.                 //    We’re not going to change window ordering,
  487.                 //    so make sure that we don’t drag in front of
  488.                 //    other windows which may be in front of ours.
  489.  
  490.                 ClipAbove(aWindow);
  491.             }
  492.             else if (IsWindowFloating(aWindow))
  493.             {
  494.                 //    We’re dragging a normal window, so make sure
  495.                 //    that we don’t drag in front of any floating
  496.                 //    windows.
  497.  
  498.                 ClipAbove(FrontWindow(kNormalWindowLayer));
  499.             }
  500.             
  501.             //    Drag an outline of the window around the desktop.
  502.             //    NOTE: DragGrayRgn destroys the region passed in, so make a copy
  503.             
  504.             RgnHandle    grayRgn = GetGrayRgn();
  505.             Rect        deskRect = (**grayRgn).rgnBBox;
  506.  
  507.             GetWindowStructureRgn(aWindow, fScratchRgn);
  508.             dragResult = DragGrayRgn(fScratchRgn, startPoint, &deskRect, &deskRect, noConstraint, nil);
  509.         }
  510.         
  511.         if ((dragResult != 0) && (dragResult != 0x80008000))
  512.         {
  513.             WindowManager::NudgeWindow(aWindow, (short) (dragResult & 0xFFFF),(short) (dragResult >> 16));
  514.         }
  515.     }
  516.  
  517.     if (!commandKeyDown)
  518.         WindowManager::SelectWindow(aWindow);
  519. }
  520.  
  521.  
  522. //--------------------------------------------------------------------------------
  523. void WindowManager::NudgeWindow(WindowRef aWindow, short horizontalDistance, short verticalDistance)
  524. {
  525.     short        newHorizontalPosition,newVerticalPosition;
  526.     RgnHandle    tempRgn = NewRgn ();
  527.  
  528.     GetWindowContentRgn ( aWindow, tempRgn );
  529.     newHorizontalPosition = (short) (**tempRgn).rgnBBox.left + horizontalDistance;
  530.     newVerticalPosition   = (short) (**tempRgn).rgnBBox.top  + verticalDistance;
  531.     DisposeRgn ( tempRgn );
  532.     
  533.     ::MoveWindow(aWindow,newHorizontalPosition,newVerticalPosition,false);
  534. }
  535.  
  536.  
  537. //--------------------------------------------------------------------------------
  538. void WindowManager::GrowWindow(WindowRef aWindow, Point startPoint, const Rect* resizeLimits)
  539. {
  540.     GrafPtr    oldPort;
  541.     long    newSize;
  542.     Rect    oldWindowRect;
  543.     
  544.     const Rect limits = {0, 0, 32000, 32000};
  545.     
  546.     if (resizeLimits = nil)
  547.     {
  548.         resizeLimits = &limits;
  549.     }
  550.     
  551.     GetPort(&oldPort);
  552.     
  553.     newSize = ::GrowWindow(aWindow, startPoint, resizeLimits);
  554.     if (newSize)
  555.     {
  556.         oldWindowRect = GetWindowPort ( aWindow )->portRect;
  557.         ::SizeWindow ( aWindow, (short) newSize, (short) (newSize >> 16), true );
  558.         SetPortWindowPort ( aWindow );
  559. //        resizeLimits = GetWindowPort ( aWindow )->portRect;
  560. //        this->AdjustForNewWindowSize(&oldWindowRect,&resizeLimits);
  561.     }
  562.     SetPort(oldPort);
  563. }
  564.  
  565.  
  566.  
  567. //--------------------------------------------------------------------------------
  568. void WindowManager::ZoomWindow(WindowRef aWindow, short zoomState, const Rect* perfectWindowRect)
  569. {
  570.     FontInfo    systemFontInfo;
  571.     short        titleBarHeight;
  572.     Rect        bestScreenRect,scratchRect;
  573.     short        amountOffscreen;
  574.     GDHandle    bestDevice;
  575.     
  576.     //    Figure out the height of the title bar so we can properly position
  577.     //    a window. The algorithm is stolen from the System 7.x 'WDEF' (0)
  578.     //
  579.     //    This probably isn’t the best thing to do: A better way might be 
  580.     //    to diff the structure and content region rectangles?
  581.  
  582.     WithWindowManagerPort wmPort;
  583.  
  584.     GetFontInfo(&systemFontInfo);
  585.     titleBarHeight = (short) (systemFontInfo.ascent + systemFontInfo.descent + 4);
  586.     if ((titleBarHeight % 2) == 1)
  587.         titleBarHeight--;
  588.     if (titleBarHeight < kMinimumTitleBarHeight)
  589.         titleBarHeight = kMinimumTitleBarHeight;
  590.  
  591.     //    Only do the voodoo magic if we are really “zooming” the window.
  592.  
  593. #if 0
  594.  
  595.     if (zoomState == inZoomOut)
  596.     {
  597.         FindScreenRectWithLargestPartOfWindow(aWindow,&bestScreenRect,&bestDevice);
  598.         bestScreenRect.top += titleBarHeight;
  599.  
  600.     //    this->GetPerfectWindowSize(&perfectWindowRect);
  601.         OffsetRect(&perfectWindowRect,-perfectWindowRect.left,-perfectWindowRect.top);
  602.  
  603.         //    Take the zero-pined perfect window size and move it to
  604.         //    the top left of the    window’s content region.
  605.  
  606.         RgnHandle    tempRgn = NewRgn ();
  607.         GetWindowContentRgn ( aWindow, tempRgn );
  608.         OffsetRect ( &perfectWindowRect,
  609.                             (**tempRgn).rgnBBox.left, (**tempRgn).rgnBBox.top );
  610.         DisposeRgn ( tempRgn );
  611.  
  612.         //    Does perfectWindowRect fit completely on the best screen?
  613.         
  614.         SectRect(&perfectWindowRect, &bestScreenRect, &scratchRect);
  615.         if (!EqualRect(&perfectWindowRect, &scratchRect))
  616.         {
  617.             //    SectRect sez perfectWindowRect doesn’t completely fit
  618.             //    on the screen, so bump the window so that more of it fits.
  619.  
  620.             //    Make sure that the left edge of perfectWindowRect is forced
  621.             //    onto the best screen.  This is in case we are bumping
  622.             //    the window to the right.
  623.  
  624.             amountOffscreen = bestScreenRect.left - perfectWindowRect.left;
  625.             if (amountOffscreen > 0)
  626.             {
  627.                 perfectWindowRect.left += amountOffscreen;
  628.                 perfectWindowRect.right += amountOffscreen;
  629.             }
  630.  
  631.             //    Make sure that the left edge of perfectWindowRect is forced
  632.             //    onto the best screen.  This is in case we are bumping
  633.             //    the window downward to a new screen.
  634.     
  635.             amountOffscreen = bestScreenRect.top - perfectWindowRect.top;
  636.             if (amountOffscreen > 0)
  637.             {
  638.                 perfectWindowRect.top += amountOffscreen;
  639.                 perfectWindowRect.bottom += amountOffscreen;
  640.             }
  641.  
  642.             //    If right edge of window falls off the screen,
  643.             //        Move window to the left until the right edge IS on the screen
  644.             //        OR the left edge is at bestScreenRect.left
  645.  
  646.             amountOffscreen = perfectWindowRect.right - bestScreenRect.right;
  647.             if (amountOffscreen > 0)
  648.             {
  649.                 //    Are we going to push the left edge offscreen? If so, change the
  650.                 //    offset so we move the window all the way over to the left.
  651.                 
  652.                 if ((perfectWindowRect.left - amountOffscreen) < bestScreenRect.left)
  653.                     amountOffscreen = perfectWindowRect.left - bestScreenRect.left;
  654.  
  655.                 perfectWindowRect.left -= amountOffscreen;
  656.                 perfectWindowRect.right -= amountOffscreen;
  657.             }
  658.  
  659.             //    If bottom edge of window falls off the screen,
  660.             //        Move window to up until the bottom edge IS on the screen
  661.             //        OR the top edge is at bestScreenRect.top
  662.  
  663.             amountOffscreen = perfectWindowRect.bottom - bestScreenRect.bottom;
  664.             if (amountOffscreen > 0)
  665.             {
  666.                 //    Are we going to push the top edge offscreen? If so, change the
  667.                 //    offset so we move the window just to the top.
  668.                 
  669.                 if ((perfectWindowRect.top - amountOffscreen) < bestScreenRect.top)
  670.                     amountOffscreen = perfectWindowRect.top - bestScreenRect.top;
  671.  
  672.                 perfectWindowRect.top -= amountOffscreen;
  673.                 perfectWindowRect.bottom -= amountOffscreen;
  674.             }
  675.  
  676.             SectRect(&perfectWindowRect, &bestScreenRect, &scratchRect);
  677.             if (!EqualRect(&perfectWindowRect, &scratchRect))
  678.             {
  679.                 //    The edges of the window still fall offscreen,
  680.                 //    so make the window smaller until it fits.
  681.                 
  682.                 if (perfectWindowRect.bottom > bestScreenRect.bottom)
  683.                     perfectWindowRect.bottom = bestScreenRect.bottom;
  684.  
  685.                 //    If the right edge is still falling off,
  686.                 //        save space for Finder’s disk icons as well.
  687.  
  688.                 if (perfectWindowRect.right > bestScreenRect.right)
  689.                 {
  690.                     perfectWindowRect.right = bestScreenRect.right;
  691.                     
  692.                     //    If we were on the main screen, leave room for Finder icons, too.
  693.                     
  694.                     if (bestDevice == GetMainDevice())
  695.                         perfectWindowRect.right -= kSpaceForFinderIcons;
  696.                 }
  697.             }
  698.         }
  699.  
  700.         //    Stash our new rectangle inside of the Window’s dataHandle
  701.         //    so that ZoomWindow does the right thing.
  702.         
  703.         SetWindowStandardState ( aWindow, &perfectWindowRect );
  704.     }
  705.  
  706. #endif
  707.  
  708.     //    HEY YOU! Don’t forget to set the port to the window being zoomed
  709.     //    Why, you ask? Because IM-IV-50 says to; otherwise you die
  710.     
  711.     WithWindowPort winPort(aWindow);
  712.  
  713.     Rect    oldWindowRect = GetWindowPort ( aWindow )->portRect;    
  714.     ::ZoomWindow(aWindow,zoomState,false);
  715.     Rect    newWindowRect = GetWindowPort ( aWindow )->portRect;
  716.  
  717. //    this->AdjustForNewWindowSize(&oldWindowRect,&newWindowRect);
  718. }
  719.  
  720. //--------------------------------------------------------------------------------
  721.  
  722.  
  723. void WindowManager::DrawWindowGrowIcon(WindowRef aWindow)
  724. {
  725.     GrafPtr        savedPort;
  726.     Rect        growBoxRect;
  727.     
  728.     GetPort(&savedPort);
  729.     SetPortWindowPort ( aWindow );
  730.     GetClip(fScratchRgn);
  731.  
  732.     //    clip to just the bottom right corner of the window
  733.     growBoxRect = GetWindowPort ( aWindow )->portRect;
  734.     growBoxRect.top        = growBoxRect.bottom - kScrollbarWidth;
  735.     growBoxRect.left    = growBoxRect.right - kScrollbarWidth;
  736.     ClipRect(&growBoxRect);
  737.  
  738.     DrawGrowIcon(aWindow);
  739.  
  740.     SetClip(fScratchRgn);
  741.     SetPort(savedPort);
  742. }
  743.  
  744.  
  745. //--------------------------------------------------------------------------------
  746. //    Routines used for dealing with windows and multiple screens
  747. //--------------------------------------------------------------------------------
  748.  
  749. struct    CalcWindowAreaDeviceLoopUserData
  750. {
  751.     GDHandle    fScreenWithLargestPartOfWindow;
  752.     long        fLargestArea;
  753.     Rect        fWindowBounds;
  754. };
  755.  
  756.  
  757. //--------------------------------------------------------------------------------
  758. pascal void CalculateWindowAreaOnDevice(short /* depth */, short /* deviceFlags */,
  759.                                         GDHandle targetDevice,long userData)
  760. {
  761.     CalcWindowAreaDeviceLoopUserData *    deviceLoopDataPtr;
  762.     long                                windowAreaOnThisScreen;
  763.     Rect                                windowRectOnThisScreen;
  764.     
  765.     deviceLoopDataPtr = (CalcWindowAreaDeviceLoopUserData *) userData;
  766.  
  767.     SectRect(&deviceLoopDataPtr->fWindowBounds, &(**targetDevice).gdRect,&windowRectOnThisScreen);
  768.     OffsetRect(&windowRectOnThisScreen,-windowRectOnThisScreen.left,-windowRectOnThisScreen.top);
  769.     windowAreaOnThisScreen = windowRectOnThisScreen.right * windowRectOnThisScreen.bottom;
  770.  
  771.     if (windowAreaOnThisScreen > deviceLoopDataPtr->fLargestArea)
  772.     {
  773.         deviceLoopDataPtr->fLargestArea = windowAreaOnThisScreen;
  774.         deviceLoopDataPtr->fScreenWithLargestPartOfWindow = targetDevice;
  775.     }
  776. }
  777.  
  778.  
  779. DeviceLoopDrawingUPP CallCalcWindowAreaOnDevice = NewDeviceLoopDrawingProc(&CalculateWindowAreaOnDevice);
  780.  
  781.  
  782. //--------------------------------------------------------------------------------
  783. void FindScreenRectWithLargestPartOfWindow(    WindowRef aWindow,Rect *theBestScreenRect,
  784.                                             GDHandle * theBestDevice)
  785. {
  786.     RgnHandle                            copyOfWindowStrucRgn;
  787.     CalcWindowAreaDeviceLoopUserData    deviceLoopData;
  788.  
  789.     //    Use DeviceLoop to find out what GDevice contains the largest
  790.     //    portion of the supplied window.
  791.     //
  792.     //    NOTE:    Assumes thePort == the Window Manager Port because we using
  793.     //            the window strucRgn, not contRgn.
  794.  
  795.     deviceLoopData.fScreenWithLargestPartOfWindow = nil;
  796.     deviceLoopData.fLargestArea = -1;
  797.  
  798.     RgnHandle    tempRgn = NewRgn ();
  799.     GetWindowContentRgn ( aWindow, tempRgn );
  800.     deviceLoopData.fWindowBounds = (**tempRgn).rgnBBox;
  801.     DisposeRgn ( tempRgn );
  802.  
  803.     copyOfWindowStrucRgn = NewRgn();
  804.     GetWindowStructureRgn ( aWindow, copyOfWindowStrucRgn );
  805.  
  806.     DeviceLoop(copyOfWindowStrucRgn,CallCalcWindowAreaOnDevice,(long) &deviceLoopData,singleDevices);    
  807.  
  808.     DisposeRgn(copyOfWindowStrucRgn);
  809.     
  810.     *theBestDevice = deviceLoopData.fScreenWithLargestPartOfWindow;
  811.     *theBestScreenRect = (**(deviceLoopData.fScreenWithLargestPartOfWindow)).gdRect;
  812.  
  813.     //    Leave some space around the edges of the screen so window look good, AND
  814.     //    if the best device is the main screen, leave space for the Menubar
  815.     
  816.     InsetRect(theBestScreenRect,kScreenEdgeSlop,kScreenEdgeSlop);
  817.     if (GetMainDevice() == deviceLoopData.fScreenWithLargestPartOfWindow)
  818.         theBestScreenRect->top += GetMBarHeight();
  819. }
  820.  
  821.  
  822.